package org.apache.cordova.wu;

import java.util.ArrayList;

import org.apache.cordova.Config;
import org.apache.cordova.ConfigXmlParser;
import org.apache.cordova.CordovaInterfaceImpl;
import org.apache.cordova.CordovaPreferences;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewEngine;
import org.apache.cordova.CordovaWebViewImpl;
import org.apache.cordova.LOG;
import org.apache.cordova.PluginEntry;
import org.apache.cordova.PluginManager;
import org.json.JSONException;

import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;


/**
 * 
 * @author 吴Sir 
 * @date 16-05-20.
 *
 */
public class CordovaFragment extends Fragment {

	public static String TAG = "CordovaFragment";

	// The webview for our app
	protected CordovaWebView appView;

	private static int Fragment_STARTING = 0;
	private static int Fragment_RUNNING = 1;
	private static int Fragment_EXITING = 2;

	// Keep app running when pause is received. (default = true)
	// If true, then the JavaScript and native code continue to run in the
	// background
	// when another application (activity) is started.
	protected boolean keepRunning = true;

	// Flag to keep immersive mode if set to fullscreen
	protected boolean immersiveMode;

	// Read from config.xml:
	protected CordovaPreferences preferences;
	protected String url;
	protected ArrayList<PluginEntry> pluginEntries;
	protected CordovaInterfaceImpl cordovaInterface;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting");
        LOG.d(TAG, "CordovaFragment.onCreate()");

        // need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception
        loadConfig();

        super.onCreate(savedInstanceState);

        cordovaInterface = makeCordovaInterface();
        if (savedInstanceState != null) {
            cordovaInterface.restoreInstanceState(savedInstanceState);
        }
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		appView = makeWebView();
        View view = createViews();
        if (!appView.isInitialized()) {
            appView.init(cordovaInterface, pluginEntries, preferences);
        }
        cordovaInterface.onCordovaInit(appView.getPluginManager());

//        // Wire the hardware volume controls to control media if desired.
//        String volumePref = preferences.getString("DefaultVolumeStream", "");
//        if ("media".equals(volumePref.toLowerCase(Locale.ENGLISH))) {
//            setVolumeControlStream(AudioManager.STREAM_MUSIC);
//        }

        // If keepRunning
        this.keepRunning = preferences.getBoolean("KeepRunning", true);

        url = getArguments().getString("url");
        appView.loadUrlIntoView(url, true);
//		return super.onCreateView(inflater, container, savedInstanceState);
        return view;
	}

	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onViewCreated(view, savedInstanceState);
		enterViewAnim();
	}

	@Override
	public void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		LOG.d(TAG, "Started the activity.");

		if (this.appView == null) {
			return;
		}
		this.appView.handleStart();
	}

	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		LOG.d(TAG, "Resumed the activity.");

		if (this.appView == null) {
			return;
		}
		// Force window to have focus, so application always
		// receive user input. Workaround for some devices (Samsung Galaxy Note
		// 3 at least)
		this.getActivity().getWindow().getDecorView().requestFocus();

		this.appView.handleResume(this.keepRunning);
	}

	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
        LOG.d(TAG, "Paused the activity.");

        if (this.appView != null) {
            // CB-9382 If there is an activity that started for result and main activity is waiting for callback
            // result, we shoudn't stop WebView Javascript timers, as activity for result might be using them
            boolean keepRunning = this.keepRunning || this.cordovaInterface.activityResultCallback != null;
            this.appView.handlePause(keepRunning);
        }
	}

	@Override
	public void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
        LOG.d(TAG, "Stopped the activity.");

        if (this.appView == null) {
            return;
        }
        this.appView.handleStop();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		LOG.d(TAG, "CordovaActivity.onDestroy()");
		super.onDestroy();

		if (this.appView != null) {
			appView.handleDestroy();
		}
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		LOG.d(TAG, "Incoming Result. Request code = " + requestCode);
        super.onActivityResult(requestCode, resultCode, data);
        cordovaInterface.onActivityResult(requestCode, resultCode, data);
	}
	
	@Override
	public void startActivityForResult(Intent intent, int requestCode) {
		// TODO Auto-generated method stub
		 // Capture requestCode here so that it is captured in the setActivityResultCallback() case.
        cordovaInterface.setActivityResultRequestCode(requestCode);
        super.startActivityForResult(intent, requestCode);
		
	}

	@Override
	public void startActivityForResult(Intent intent, int requestCode,
			Bundle options) {
		// TODO Auto-generated method stub
		 // Capture requestCode here so that it is captured in the setActivityResultCallback() case.
        cordovaInterface.setActivityResultRequestCode(requestCode);
        super.startActivityForResult(intent, requestCode, options);
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		// TODO Auto-generated method stub
		if (appView != null) {
			appView.getPluginManager().postMessage("onCreateOptionsMenu", menu);
		}
		super.onCreateOptionsMenu(menu, inflater);
	}

	@Override
	public void onPrepareOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		if (appView != null) {
			appView.getPluginManager().postMessage("onPrepareOptionsMenu", menu);
		}
		super.onPrepareOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		if (appView != null) {
			appView.getPluginManager().postMessage("onOptionsItemSelected", item);
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
		cordovaInterface.onSaveInstanceState(outState);
		super.onSaveInstanceState(outState);
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		// TODO Auto-generated method stub
		super.onConfigurationChanged(newConfig);
        if (this.appView == null) {
            return;
        }
        PluginManager pm = this.appView.getPluginManager();
        if (pm != null) {
            pm.onConfigurationChanged(newConfig);
        }
	}

	@Override
	public void onRequestPermissionsResult(int requestCode,
			String[] permissions, int[] grantResults) {
		// TODO Auto-generated method stub
		try {
			cordovaInterface.onRequestPermissionResult(requestCode, permissions, grantResults);
		} catch (JSONException e) {
			LOG.d(TAG, "JSONException: Parameters fed into the method are not valid");
			e.printStackTrace();
		}
	}
	
	@SuppressWarnings("deprecation")
    protected void loadConfig() {
        ConfigXmlParser parser = new ConfigXmlParser();
        parser.parse(getActivity());
        preferences = parser.getPreferences();
        preferences.setPreferencesBundle(getActivity().getIntent().getExtras());
//        launchUrl = parser.getLaunchUrl();
        pluginEntries = parser.getPluginEntries();
        Config.parser = parser;
    }

	protected View createViews() {
		RelativeLayout view = new RelativeLayout(getActivity());
		view.setLayoutParams(new RelativeLayout.LayoutParams(
				RelativeLayout.LayoutParams.MATCH_PARENT,
				RelativeLayout.LayoutParams.MATCH_PARENT));
		// Why are we setting a constant as the ID? This should be investigated
		appView.getView().setId(100);
		appView.getView().setLayoutParams(
				new FrameLayout.LayoutParams(
						ViewGroup.LayoutParams.MATCH_PARENT,
						ViewGroup.LayoutParams.MATCH_PARENT));
		view.addView(appView.getView());

		RelativeLayout contenter = new RelativeLayout(getActivity());
		contenter.setId(NaviManager.CONTENTER_ID);
		contenter.setLayoutParams(new RelativeLayout.LayoutParams(
				RelativeLayout.LayoutParams.MATCH_PARENT,
				RelativeLayout.LayoutParams.MATCH_PARENT));
		contenter.setVisibility(View.GONE);
		view.addView(contenter);

		// setContentView(view);

		if (preferences.contains("BackgroundColor")) {
			int backgroundColor = preferences.getInteger("BackgroundColor",
					Color.BLACK);
			// Background of activity:
			appView.getView().setBackgroundColor(backgroundColor);
		}

		appView.getView().requestFocusFromTouch();

		return view;
	}
	  
	 /**
     * Construct the default web view object.
     * <p/>
     * Override this to customize the webview that is used.
     */
    protected CordovaWebView makeWebView() {
        return new CordovaWebViewImpl(makeWebViewEngine());
    }

    protected CordovaWebViewEngine makeWebViewEngine() {
        return CordovaWebViewImpl.createEngine(getActivity(), preferences);
    }

    protected CordovaInterfaceImpl makeCordovaInterface() {
        return new CordovaInterfaceImpl(this) {
            @Override
            public Object onMessage(String id, Object data) {
                // Plumb this to CordovaActivity.onMessage for backwards compatibility
                return CordovaFragment.this.onMessage(id, data);
            }
        };
    }

	protected Object onMessage(String id, Object data) {
//        if ("onReceivedError".equals(id)) {
//            JSONObject d = (JSONObject) data;
//            try {
//                this.onReceivedError(d.getInt("errorCode"), d.getString("description"), d.getString("url"));
//            } catch (JSONException e) {
//                e.printStackTrace();
//            }
//        } else if ("exit".equals(id)) {
//            finish();
//        }
        return null;
    }
	
	//-----------------------------------------
	/**
	 * 页面还原动画
	 */
	public void restoreViewAnim() {
		WindowManager windowManager = (WindowManager)  getActivity().getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		windowManager.getDefaultDisplay().getMetrics(outMetrics);
		float offset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, outMetrics);
		TranslateAnimation animation = new TranslateAnimation(-offset, 0, 0, 0);
		animation.setDuration(500);
		getView().startAnimation(animation);
	}
	
	/**
	 * 页面进入后台动画
	 */
	public void saveViewAnim() {
		WindowManager windowManager = (WindowManager)  getActivity().getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		windowManager.getDefaultDisplay().getMetrics(outMetrics);
		float offset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, outMetrics);
		TranslateAnimation animation = new TranslateAnimation(0, -offset, 0, 0);
		animation.setDuration(500);
		getView().startAnimation(animation);
	}
	
	/**
	 * 进入页面动画
	 */
	public void enterViewAnim() {
		WindowManager windowManager = (WindowManager)  getActivity().getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		windowManager.getDefaultDisplay().getMetrics(outMetrics);
		TranslateAnimation animation = new TranslateAnimation(outMetrics.widthPixels, 0, 0, 0);
		animation.setDuration(500);
		getView().startAnimation(animation);
	}
	
	/**
	 * 退出页面动画
	 */
	public void exitViewAnim() {
		WindowManager windowManager = (WindowManager)  getActivity().getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics outMetrics = new DisplayMetrics();
		windowManager.getDefaultDisplay().getMetrics(outMetrics);
		TranslateAnimation animation = new TranslateAnimation(0, outMetrics.widthPixels, 0, 0);
		animation.setDuration(500);
		animation.setAnimationListener(new Animation.AnimationListener() {
			
			@Override
			public void onAnimationStart(Animation animation) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onAnimationRepeat(Animation animation) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onAnimationEnd(Animation animation) {
				// TODO Auto-generated method stub
				FragmentManager fm = getFragmentManager();
				if (fm != null) {
					FragmentTransaction ft = fm.beginTransaction();
					ft.remove(CordovaFragment.this);
					ft.commitAllowingStateLoss();
					fm.popBackStack();
				} else {
					LOG.e("error", "getFragmentManager is null, fm.popBackStack() 未执行");
				}
			}
		});
		getView().startAnimation(animation);
	}

}
